# odecurve by kristoffer josefsson

from polygon import *
from scipy import *
from random import *

class polyODE(polyGL):
	
	def __init__(self):
		polyGL.__init__(self)
		self.b = 0.5;
		
	def randomize(self):
		self.b = randint(0,100)/100.0	

	def update(self, a):
		self.a = a

	def compute(self):

		# we won't use t as parameter for the curve because it is used as "tangent".
		# anyhow we pretend the curved is parametrized by arclength ad dS sounds fine.

		def K(s):
			return self.b+sin(sin(5*self.a)*s**self.b);

		def T(s):
			return 3**-self.b*tan(self.a/2.0);

		# solve curve by curvature and torsion
		# t = tangent, n = normal, b = binormal
		# we have to solve the whole frame. slow? don't know any faster way.
		def frenetFrame(y,s):

			k = K(s);
			t = T(s);

			res = [y[3], y[4], y[5],
					k*y[6], k*y[7], k*y[8],t*y[9] - k*y[3], 
					t*y[10] - k*y[4], t*y[11] - k*y[5],
					t*y[6], t*y[7], t*y[8]];
			
	#		ts = 1/sqrt(res[3]**2 + res[4]**2 + res[5]**2);
	#		res[3:6] = [res[3]*ts, res[4]*ts, res[5]*ts];

	#		ns = 1/sqrt(res[6]**2 + res[7]**2 + res[8]**2);
	#		res[6:9] = [res[6]*ns, res[7]*ns, res[8]*ns];

	#		bns = 1/sqrt(res[9]**2 + res[10]**2 + res[11]**2);
	#		res[9:12] = [res[9]*bns, res[10]*bns, res[11]*bns];

			return res;

##			y.shape = (4,3);

##			res = array([y[1], 
##					K(s)*y[2],
##					-K(s)*y[1] + T(s)*y[3],

##					-T(s)*y[1]]);

##			res.shape = (1,12);
##			return atov(res);

		# only a test..
		def func(y,s):
			return [sin(pi*a)*s**2*y[1]+sin(pi*a*s)*y[0],y[0],s+sin(a+s)]
	
		# todo, get rid of to improve perf.
		def atov(a):
			return (map(lambda x: vector(x), a))

		y0 = [0,0,0,
			  -1,0,0,
			  0,1,0,
			  0,0,-1
			 ];

		y1 = [0,0,1];
		s = arange(0,4 * pi,0.2)

		self.res = integrate.odeint(frenetFrame, y0, s)

		self.vert = atov([self.res[i][0:3] for i in range(0,size(s))])
		self.tan = atov([self.res[i][3:6] for i in range(0,size(s))])
		self.norm = atov([self.res[i][6:9] for i in range(0,size(s))])
		self.binorm = atov([self.res[i][9:12] for i in range(0,size(s))])

		self.closed = False
		self.prepare()
		self.redraw = True
